;; this file is responsible for setting up paging with the kernel in
;; the higher half. 
;; Kernel appears at 0xC0000000 
;; Heap appears at   0xD0000000

global _cr1
global pde_orig
extern kmain
[bits 32]
[section .cr1_text]

;;; this is here because the table are linked in at the
;;; end of the kernel, and their addresses have this offset
OFFSET	equ	0xc0000000

;;; set by linker. marks beginning of free memory
extern END

_cr1:
	xor eax, eax
	mov eax, 0x10
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov esp, 0xe0000fff
	mov fs, ax
	mov gs, ax

;;; setup paging
	mov ebx, (END + 0x00100000)
	or ebx, 0x3
	mov ecx, 0
	mov eax, 0x00000003

kernel_loop:
	mov dword [kernel_pte + ecx*4 - OFFSET], eax
	add eax, 0x1000
	inc ecx
	cmp ecx, 1024
	jnz kernel_loop

	mov ecx, 0
	
;;; use a different loop for heap because initially only 1mb is mapped
heap_loop:
	mov dword [heap_pte + ecx*4 - OFFSET], ebx
	add ebx, 0x1000
	inc ecx
	cmp ecx, 256
	jnz heap_loop
	
end:
	;;; first setup stack to exist at 0x0001f000
	mov eax, 0x0001f003
	mov dword [stack_pte - OFFSET], eax
	;;; now set table entries in directory
	mov eax, (kernel_pte - OFFSET)
	mov ebx, (heap_pte - OFFSET)
	mov ecx, (stack_pte - OFFSET)
	or eax, 0x00000003
	or ebx, 0x00000003
	or ecx, 0x00000003
	
	;;;  identity map first 4 mb
	mov dword [pde_orig - OFFSET], eax

	;;;  also map 0xC0000000 => 0x00000000
	mov dword [pde_orig + 768*4 - OFFSET], eax

	;;; map 0xD0000000 => END_OF_KERNEL
	mov dword [pde_orig + 832*4 - OFFSET], ebx

        ;;; map stack at 0xE0000000
	mov dword [pde_orig + 896*4 - OFFSET], ecx

	mov eax, (pde_orig - OFFSET)
	mov cr3, eax
	mov eax, cr0
	or eax, 0x80000000
	mov cr0, eax

blank:	nop
	nop
	nop
	
	call kmain


;;; these will later be stored in data structures to be
;;; accessed by the kernel. This way we can set them up
;;; here, and just point to them when we initialise paging
[section .cr1_data]
pde_orig: times 1024     dd 0

;;; maps 0-4 MB
kernel_pte: times 1024	 dd 0

;;; maps page tables for the heap
heap_pte: times 1024 	 dd 0

;;; stack pte
stack_pte: times 1024    dd 0



